<!--
  功能：列表页面，包含【搜索栏，操作栏，表格，分页】
  作者：陈广安
  时间：2023年07月26日 16:08:47
-->
<template>
  <!-- 条件筛选栏 -->
  <div class="c1" v-if="slotSearch">
    <slot name="search">
      <div class="flex search">
        <el-select
          v-if="isShowTypeSelect"
          clearable
          v-model="pData.type_id"
          placeholder="筛选分类"
          @change="reload"
        >
          <el-option
            v-for="item in modelValue.types"
            :key="item.id"
            :label="item.name"
            :value="item.id"
          />
        </el-select>

        <el-input
          placeholder="请输入搜索关键词"
          v-model="pData.searchVal"
          @keyup.enter.native="reload"
          clearable
          @clear="resetFn"
        >
          <template #append
            ><el-button @click="reload">搜索</el-button></template
          >
        </el-input>
        <div class="v1"><el-button @click="resetFn">重置</el-button></div>
      </div>
    </slot>
  </div>

  <div class="c2">
    <!-- 操作栏 -->
    <div class="c3" v-if="slotAction">
      <slot name="action"></slot>
    </div>

    <!-- 表格 -->
    <el-table
      :data="modelValue.lists"
      v-loading="modelValue.loading ?? false"
      style="width: 100%"
      stripe
      row-key="id"
      :default-expand-all="defaultExpandAll"
      :max-height="getTableHeight"
      @selection-change="selectChecked"
      @sort-change="sortChange"
      :default-sort="{
        prop: pData.sortField,
        order: pData.sort == 'desc' ? 'descending' : 'ascending',
      }"
    >
      <el-table-column type="selection" width="55" v-if="isCheck" />
      <slot></slot>
    </el-table>

    <!-- 分页栏 -->
    <div class="flex c4" v-if="pageSizes.length">
      <el-pagination
        background
        @current-change="reload"
        @size-change="switchSizeChange"
        v-model:currentPage="pData.page"
        :default-page-size="pData.limit"
        layout="total, sizes,prev, pager, next"
        :total="modelValue.total"
        :page-sizes="pageSizes"
      ></el-pagination>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { tableDataType, tableDataQuery } from "@/common/interface";
import type { TableColumnCtx } from "element-plus";

const emit = defineEmits<{
  (e: "update:modelValue", data: tableDataType<any>): void; //更新勾选的数据
  (e: "getList", data: tableDataQuery): void; //向父组件传递 需要请求分页数据
}>();

interface IProps {
  modelValue: tableDataType<any>;
  isCheck?: boolean;
  pageSizes?: number[];
  defaultExpandAll?: boolean;
  isShowTypeSelect?: boolean;
  sortField?: string;
  sort?: string;
}
const props = withDefaults(defineProps<IProps>(), {
  modelValue: () => new tableDataType(),
  isCheck: () => true, //是否需要显示多选框列表 默认显示
  defaultExpandAll: () => true, //是否需要展开行
  isShowTypeSelect: () => true, //是否需要显示下拉分类筛选
  pageSizes: () => [30, 50, 100], //每页显示个数选择器的选项设置
  sortField: () => "id",//默认排序字段
  sort: () => "desc",//默认排序方式
});

const pData = reactive<tableDataQuery>({
  page: 1,
  limit: props.pageSizes[0],
  searchVal: "",
  type_id: undefined,
  sortField: props.sortField,
  sort: props.sort,
});

onMounted(() => {
  emit("getList", pData);
});

//判断插槽是否使用
const slotSearch = !!useSlots().search;
const slotAction = !!useSlots().action;

//计算表格高度
const getTableHeight = computed(() => {
  let h = 135;
  //根据插槽 是否使用来获取高度
  if (slotSearch) h += 52;
  if (slotAction) h += 42;

  //判断是否需要分页
  if (props.pageSizes.length) h += 42;
  return `calc(100vh - ${h}px)`;
});

//获取勾选的数据
function selectChecked(data: any) {
  console.log(data);
  props.modelValue.checkItem = data;
  emit("update:modelValue", props.modelValue);
}

//切换每一页的条数
function switchSizeChange(val: number) {
  pData.limit = val;
  getList();
}

//点击分页 | 刷新 | 搜索
function reload() {
  getList();
}

//重置搜索
function resetFn() {
  pData.searchVal = "";
  pData.type_id = undefined;
  pData.page = 1;
  getList();
}

function sortChange(e: {
  column: TableColumnCtx<any>;
  prop: string;
  order: string;
}) {
  if (e.order) {
    pData.sortField = e.prop;
    pData.sort = e.order === "descending" ? "desc" : "asc";
  } else {
    pData.sortField = "id";
    pData.sort = "desc";
  }
  getList();
}

function getList() {
  emit("getList", pData);
}

defineExpose({
  reload,
});
</script>

<style lang="scss" scoped>
.c1 {
  padding: 10px;
  background: #fff;
  // margin-bottom: 10px;
}
.c2 {
  padding: 10px;
}
.c3 {
  margin-bottom: 10px;
}
.c4 {
  margin-top: 10px;
  flex-direction: row-reverse;
}

.search {
  .el-select {
    margin-right: 20px;
  }
  .v1 {
    margin-left: 10px;
  }
}

html.dark {
  .c1 {
    background: #222;
  }
}
</style>
